#include <iostream>
#include <string>
#include <cassert>
#include <signal.h>
#include <unistd.h>
void sigcb(int sig)
{
  std::cout << "get a signal:" << sig << std::endl;
}

// int main()
// {
//   struct sigaction act, oact;
//   act.sa_handler = sigcb;
//   act.sa_flags = 0;
//   sigemptyset(&act.sa_mask);

//   sigaction(SIGINT, &act, &oact);
//   while (true)
//   {
//     /* code */
//   }

//   return 0;
// }
// int main()
// {
//   sigset_t block, oblock;
//   sigemptyset(&block);
//   sigemptyset(&oblock);
//   sigaddset(&block, 2);
//   sigaddset(&block, 40);
//   int n = sigprocmask(SIG_SETMASK, &block, &oblock);
//   assert(n == 0);
//   while (true)
//     ;
// }
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

int tickets = 1000;
pthread_mutex_t mutex;
void *TicketGrabbing(void *arg)
{
  const char *name = (char *)arg;
  while (1)
  {
    pthread_mutex_lock(&mutex);
    if (tickets > 0)
    {
      usleep(100);
      printf("[%s] get a ticket, left: %d\n", name, --tickets);
      pthread_mutex_unlock(&mutex);
    }
    else
    {
      pthread_mutex_unlock(&mutex);
      break;
    }
  }
  printf("%s quit!\n", name);
  pthread_exit((void *)0);
}
int main()
{
  pthread_mutex_init(&mutex, NULL);
  pthread_t t1, t2, t3, t4;
  pthread_create(&t1, NULL, TicketGrabbing, (void *)"thread 1");
  pthread_create(&t2, NULL, TicketGrabbing, (void *)"thread 2");
  pthread_create(&t3, NULL, TicketGrabbing, (void *)"thread 3");
  pthread_create(&t4, NULL, TicketGrabbing, (void *)"thread 4");

  pthread_join(t1, NULL);
  pthread_join(t2, NULL);
  pthread_join(t3, NULL);
  pthread_join(t4, NULL);
  pthread_mutex_destroy(&mutex);
  return 0;
}
